#include "Grid.h"

Grid::Grid(int m, int n, float dx)
	: numVertices(0)
	, numFaces(0)
{
	numVertices = (++m) * (++n);
	numFaces = n * m * 2;

	BuildVertexBuffer(m, n, dx);
	BuildIndexBuffer(m, n);

	HR(D3DXCreateEffectFromFile( gd3dDevice
							, "Fog.fx"
							, 0, 0,
							D3DXSHADER_DEBUG
							, 0, &mFX
							, &errors));
	if(errors)
		MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);

	mhWVP = mFX->GetParameterByName(0, "gWVP");
	mhEyePos = mFX->GetParameterByName(0, "gEyePos");
	//mhTime = mFX->GetParameterByName(0, "gTime");
	mhTech = mFX->GetTechniqueByName("TransformTech");
}

Grid::~Grid()
{
	ReleaseCOM(mVB);
	ReleaseCOM(mIB);
}

void Grid::OnResetDevice()
{
	mFX->OnResetDevice();
}

void Grid::OnLostDevice()
{
	mFX->OnLostDevice();
}

void Grid::DrawGrid(D3DXMATRIX &mView, D3DXMATRIX &mProj, D3DXVECTOR3 &eyePos, float totalTime)
{
	gd3dDevice->SetStreamSource(0, mVB, 0, sizeof(VertexCol));
	gd3dDevice->SetIndices(mIB);
	gd3dDevice->SetVertexDeclaration(VertexCol::decl);

	HR(mFX->SetTechnique(mhTech));
	HR(mFX->SetValue(mhEyePos, eyePos, sizeof(D3DXVECTOR3)));
	//HR(mFX->SetFloat(mhTime, totalTime));

	UINT numPasses = 0;
	HR(mFX->Begin(&numPasses, 0));
	for(int i = 0; i < numPasses; ++i)
	{
		HR(mFX->BeginPass(i));

		HR(mFX->SetMatrix(mhWVP, &(mView * mProj)));
		mFX->CommitChanges();

		HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVertices, 0, numFaces));

		HR(mFX->EndPass());
	}

	//gd3dDevice->SetTransform(D3DTS_WORLD, &(R * Tf * Tl));

	HR(mFX->End());

}

void Grid::BuildVertexBuffer(int m, int n, float dx)
{
	HR(gd3dDevice->CreateVertexBuffer( numVertices * sizeof(VertexCol)
		, D3DUSAGE_WRITEONLY
		, 0, D3DPOOL_MANAGED
		, &mVB, 0));

	VertexCol* vertices = 0;
	HR(mVB->Lock(0, 0, (void**)&vertices, 0));

	float halfWidth = (n-1) * dx * 0.5f;
	float halfDepth = (m-1) * dx * 0.5f;
	for(DWORD i = 0; i < m; ++i)
	{
		float z = halfDepth - i * dx;
		float y = 0.0f;
		for(DWORD j = 0; j < n; ++j)
		{
			float x = -halfWidth + j * dx;
			
			vertices[i * n + j].pos = D3DXVECTOR3(x, y, z);
			vertices[i * n + j].col = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
		}
	}
	HR(mVB->Unlock());
}

void Grid::BuildIndexBuffer(int m, int n)
{
	HR(gd3dDevice->CreateIndexBuffer((m * 6) * (n * 6) * sizeof(DWORD)
								, D3DUSAGE_WRITEONLY
								, D3DFMT_INDEX32
								, D3DPOOL_MANAGED
								, &mIB
								, 0));

	DWORD* indices = 0;
	HR(mIB->Lock(0, 0, (void**)&indices, 0));

	// Iterate over each quad and compute indices.
	int k = 0;
	for(DWORD i = 0; i < m-1; ++i)
	{
		for(DWORD j = 0; j < n-1; ++j)
		{
			indices[k] = i*n+j;
			indices[k+1] = i*n+j+1;
			indices[k+2] = (i+1)*n+j;
			indices[k+3] = (i+1)*n+j;
			indices[k+4] = i*n+j+1;
			indices[k+5] = (i+1)*n+j+1;
			k += 6; // next quad
		}
	}

	HR(mIB->Unlock());
}

